package com.brillilab.service.core.topics.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.dao.mapper.topics.TopicExperimentMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.plans.Plan;
import com.brillilab.domain.po.plans.PlanExperimentGroup;
import com.brillilab.domain.po.plans.PlanTargetGroup;
import com.brillilab.domain.po.topics.TopicExperiment;
import com.brillilab.domain.vo.topics.TopicExperimentVo;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.plans.IPlanExperimentGroupService;
import com.brillilab.service.core.plans.IPlanService;
import com.brillilab.service.core.plans.IPlanTargetGroupService;
import com.brillilab.service.core.system.IFileManageService;
import com.brillilab.service.core.topics.ITopicExperimentService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Transactional
public class TopicExperimentServiceImpl implements ITopicExperimentService {

	@Resource
	private TopicExperimentMapper topicExperimentMapper;
	@Resource
	private IExperimentService experimentService;
	@Resource
	private IPlanExperimentGroupService planExperimentGroupService;
	@Resource
	private IPlanService planService;
	@Resource
	private IFileManageService fileManageService;
	@Resource
	private IPlanTargetGroupService planTargetGroupService;
	
	@Override
	public List<TopicExperiment> getTopicExperimentList(Long targetId) {
		LambdaQueryWrapper<TopicExperiment> queryWrapper = new LambdaQueryWrapper<TopicExperiment>();
		queryWrapper.eq(TopicExperiment::getTopicTargetId, targetId);
		queryWrapper.eq(TopicExperiment::getIsDelete, IsDeleteEnum.NO.getValue());
		return topicExperimentMapper.selectList(queryWrapper);
	}
	
	@Override
	public List<TopicExperiment> getTopicExperimentListByDirectionId(Long directionId) {
		LambdaQueryWrapper<TopicExperiment> queryWrapper = new LambdaQueryWrapper<TopicExperiment>();
		queryWrapper.eq(TopicExperiment::getTopicDirectionId, directionId);
		queryWrapper.eq(TopicExperiment::getIsDelete, IsDeleteEnum.NO.getValue());
		return topicExperimentMapper.selectList(queryWrapper);
	}
	
	@Override
	public List<TopicExperiment> getTopicExperimentList(Long targetId, Integer isCheck) {
		LambdaQueryWrapper<TopicExperiment> queryWrapper = new LambdaQueryWrapper<TopicExperiment>();
		queryWrapper.eq(TopicExperiment::getTopicTargetId, targetId);
		queryWrapper.eq(TopicExperiment::getIsCheck, isCheck);
		queryWrapper.eq(TopicExperiment::getIsDelete, IsDeleteEnum.NO.getValue());
		return topicExperimentMapper.selectList(queryWrapper);
	}
	
	@Override
	public List<TopicExperimentVo> getTopicExperimentVoList(Long targetId) {
		return topicExperimentMapper.getTopicExperimentVoList(targetId);
	}

	@Override
	public int getCount(Long targetId, Integer isCheck, Integer isDelete) {
		LambdaQueryWrapper<TopicExperiment> queryWrapper = new LambdaQueryWrapper<TopicExperiment>();
		queryWrapper.eq(TopicExperiment::getTopicTargetId, targetId);
		if (isCheck != null)
			queryWrapper.eq(TopicExperiment::getIsCheck, isCheck);
		if (isDelete != null)
			queryWrapper.eq(TopicExperiment::getIsDelete, isDelete);
		return topicExperimentMapper.selectCount(queryWrapper);
	}

	@Override
	public TopicExperiment insert(TopicExperiment topicExperiment) {
		int insert = topicExperimentMapper.insert(topicExperiment);
		Assert.isTrue(insert==1, "添加失败");
		return topicExperiment;
	}
	
	@Override
	public boolean updateById(TopicExperiment topicExperiment) {
		return topicExperimentMapper.updateById(topicExperiment) >0;
	}
	
	@Override
	public TopicExperiment selectById(Long topicExperimentId) {
		return topicExperimentMapper.selectById(topicExperimentId);
	}
	
	@Override
	public void deleteById(TopicExperiment topicExperiment) {
		Long topicExperimentId = topicExperiment.getId();
		int count = 0;
		if(BoolEnum.TRUE.getValue().equals(topicExperiment.getIsCheck())) {
			List<Experiment> list = experimentService.getExperimentList(topicExperimentId, null);
			if(CollectionUtils.isNotEmpty(list)) {
				List<Long> experimentIdS = list.stream().map(Experiment::getId).collect(Collectors.toList());
				count = fileManageService.selectCount(Arrays.asList(OssFileEnum.AnalyzeDataFile.getKey(),OssFileEnum.PrimaryDataFile.getKey()), 
						experimentIdS);
			}
		}
		
		TopicExperiment target = new TopicExperiment();
		target.setId(topicExperimentId);
		if(count==0) {
			TopicExperiment lastOne = this.getLastOne(topicExperiment.getTopicTargetId(), topicExperiment.getIsCheck());
			if(lastOne!=null && !lastOne.getId().equals(topicExperimentId)) {
				target.setIsDelete(IsDeleteEnum.YES.getValue());
				int b = topicExperimentMapper.updateById(target);
				Assert.isTrue(b==1, "删除失败");
			}else {
				int b = topicExperimentMapper.deleteById(topicExperimentId);
				Assert.isTrue(b==1, "删除失败");
			}
			experimentService.delete(null, null, topicExperimentId);
		}else {
			target.setIsDelete(IsDeleteEnum.NULLIFY.getValue());
			int b = topicExperimentMapper.updateById(target);
			Assert.isTrue(b==1, "作废失败");
		}
		planExperimentGroupService.delete(topicExperimentId);
		planService.deleteByTopicExperimentId(topicExperimentId);
	}
	
	@SuppressWarnings("unchecked")
	private TopicExperiment getLastOne(Long targetId, Integer isCheck) {
		LambdaQueryWrapper<TopicExperiment> queryWrapper = new LambdaQueryWrapper<TopicExperiment>();
		queryWrapper.eq(TopicExperiment::getTopicTargetId, targetId);
		queryWrapper.eq(TopicExperiment::getIsCheck, isCheck);
		queryWrapper.orderByDesc(TopicExperiment::getId);
		List<TopicExperiment> list = topicExperimentMapper.selectList(queryWrapper);
		return CollectionUtils.isNotEmpty(list)?list.get(0):null;
		
	}

	@Override
	public void recovery(Long topicExperimentId) {
		TopicExperiment topicExperiment = topicExperimentMapper.selectById(topicExperimentId);
		int count = this.getCount(topicExperiment.getTopicTargetId(), BoolEnum.TRUE.getValue(), BoolEnum.FALSE.getValue());
		Assert.isTrue(count<=6, "进行中检测实验目标最多6个");
		List<TopicExperiment> teList = this.getTopicExperimentList(topicExperiment.getTopicTargetId());
		if(CollectionUtils.isNotEmpty(teList)) {
			Optional<TopicExperiment> optional = teList.stream().filter(te -> te.getMethodTypeId().equals(topicExperiment.getMethodTypeId())).findFirst();
			Assert.isTrue(!optional.isPresent(), "已存在 "+topicExperiment.getMethodTypeName()+" 实验，请作废现有的才可恢复。");
		}
		topicExperiment.setId(topicExperimentId);
		topicExperiment.setIsDelete(IsDeleteEnum.NO.getValue());
		int b = topicExperimentMapper.updateById(topicExperiment);
		Assert.isTrue(b==1, "恢复失败");
		
		 PlanTargetGroup targetGroup = planTargetGroupService.getNewestPlanTargetGroup(topicExperiment.getTopicTargetId());
		 if(targetGroup!=null) {
			 PlanExperimentGroup experimentGroup = new PlanExperimentGroup();
			 experimentGroup.setTargetGroupId(targetGroup.getId());
			 experimentGroup.setTopicExperimentId(topicExperimentId);
			 PlanExperimentGroup experimentGroup2 = planExperimentGroupService.insert(experimentGroup);
			 
			 List<Experiment> list = experimentService.getExperimentList(topicExperimentId, null);
			 if(CollectionUtils.isNotEmpty(list)) {
				 list.forEach(experiment -> {
					if(experiment.getStartTime()!=null) {
						Plan plan = new Plan();
						plan.setLabId(experiment.getLabId());
						plan.setTopicId(experiment.getTopicId());
						plan.setTopicDirectionId(experiment.getTopicDirectionId());
						plan.setTopicTargetId(experiment.getTopicTargetId());
						plan.setTopicExperimentId(experiment.getTopicExperimentId());
						plan.setExperimentId(experiment.getId());
						
						plan.setTargetGroupId(targetGroup.getId());
						plan.setExperimentGroupId(experimentGroup2.getId());
						plan.setLabMemberId(experiment.getExecutorId());
						Date planTime = planService.getPlanTime(experiment.getExecutorId(), experiment.getStartTime(), 1);
						plan.setPlanTime(planTime);
						plan = planService.insert(plan);
					} 
				 });
			 } 
		 }
	}

	@Override
	public TopicExperimentVo getTopicExperimentVo(Long topicExperimentId) {
		return topicExperimentMapper.getTopicExperimentVo(topicExperimentId);
	}

	@Override
	public List<TopicExperimentVo> getExperimentGuideList(List<Long> experimentIds) {
		return topicExperimentMapper.getExperimentGuideList(experimentIds);
	}

	@Override
	public List<TopicExperiment> getTopicExperimentList(List<Long> topicExperimentIds) {
		LambdaQueryWrapper<TopicExperiment> wrapper = new LambdaQueryWrapper<TopicExperiment>();
		if(!CollectionUtils.isEmpty(topicExperimentIds))
			wrapper.in(TopicExperiment::getId,topicExperimentIds);
		wrapper.eq(TopicExperiment::getIsDelete, BoolEnum.FALSE.getValue());
		return topicExperimentMapper.selectList(wrapper);
	}

	@Override
	public void delete(Long topicDirectionId, Long topicTargetId) {
		if(topicDirectionId!=null || topicTargetId!=null) {
			
			TopicExperiment target = new TopicExperiment();
			target.setIsDelete(BoolEnum.TRUE.getValue());
			
			LambdaQueryWrapper<TopicExperiment> wrapper = new LambdaQueryWrapper<TopicExperiment>();
			if(topicDirectionId!=null)
				wrapper.eq(TopicExperiment::getTopicDirectionId,topicDirectionId);
			if(topicTargetId!=null)
				wrapper.eq(TopicExperiment::getTopicTargetId,topicTargetId);
			topicExperimentMapper.update(target, wrapper);
		}
	}

    @Override
    public boolean hasPublishResult(Long topicExperimentId) {
		TopicExperiment topicExperiment=topicExperimentMapper.selectById(topicExperimentId);
		Assert.notNull(topicExperiment,"实验目标不存在!");
		return BoolEnum.FALSE.getValue().equals(topicExperiment.getIsPublish());
    }

	@Override
	public int getCount(Long topicId) {
		LambdaQueryWrapper<TopicExperiment> queryWrapper = new LambdaQueryWrapper<TopicExperiment>();
		queryWrapper.eq(TopicExperiment::getTopicId, topicId);
		return topicExperimentMapper.selectCount(queryWrapper);
	}

	@Override
	public int getCountByLabId(Long labId) {
		return topicExperimentMapper.getTopicExperimentCountByLabId(labId);
	}

	@Override
	public int getCountByLabMemberId(Long labId,Long labMemberId) {
		return topicExperimentMapper.getTopicExperimentCountByLabMemberId(labId,labMemberId);
	}

	@Override
	public List<TopicExperiment> getTopicExperimentByTargetGroupId(Long targetGroupId) {
		return topicExperimentMapper.getTopicExperimentByTargetGroupId(targetGroupId);
	}

	@Override
	public List<TopicExperiment> getTopicExperimentList(Long targetId, Long methodTypeId) {
		LambdaQueryWrapper<TopicExperiment> queryWrapper = new LambdaQueryWrapper<TopicExperiment>();
		queryWrapper.eq(TopicExperiment::getTopicTargetId, targetId);
		queryWrapper.eq(TopicExperiment::getMethodTypeId, methodTypeId);
		queryWrapper.eq(TopicExperiment::getIsDelete, IsDeleteEnum.NO.getValue());
		return topicExperimentMapper.selectList(queryWrapper);
	}

	@Override
	public List<TopicExperiment> getAllTopicExperimentList(Long targetId) {
		LambdaQueryWrapper<TopicExperiment> queryWrapper = new LambdaQueryWrapper<TopicExperiment>();
		queryWrapper.eq(TopicExperiment::getTopicTargetId, targetId);
		return topicExperimentMapper.selectList(queryWrapper);
	}

}
